package czk.concrent.synControl.practice;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Author:ChenZhangKun
 * @Date: 2020/12/30 22:44
 */
public class ReentrantLockDemo {
    public static void main(String[] args) throws InterruptedException {
        MyReentrantLock lock = new MyReentrantLock(5);
        // 第一个休息室
        Condition condition = lock.newCondition();
        // 第二个
        Condition condition1 = lock.newCondition();
        // 第三个
        Condition condition2 = lock.newCondition();
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 3; i++) {
            int k = i;
            executorService.submit(() -> {
                if (k == 0) {
                    lock.print("A", condition, condition1);
                }
                if (k == 1) {
                    lock.print("B", condition1, condition2);
                }
                if (k == 2) {
                    lock.print("C", condition2, condition);
                }
            });
        }
        Thread.sleep(1000);
        try {
            lock.lock();
            condition.signal();
        } finally {
            lock.unlock();
        }
        TimeUnit.SECONDS.sleep(3);
        executorService.shutdown();
        System.out.println();

        ReentrantLockDemoPra reentrantLockDemoPra=new ReentrantLockDemoPra(5);
        // 第一个休息室
        Condition condition3= reentrantLockDemoPra.newCondition();
        // 第二个
        Condition condition4 = reentrantLockDemoPra.newCondition();
        // 第三个
        Condition condition5 = reentrantLockDemoPra.newCondition();
        new Thread(()->{
            reentrantLockDemoPra.print("a",condition3,condition4);
        }).start();
        new Thread(()->{
            reentrantLockDemoPra.print("b",condition4,condition5);
        }).start();
        new Thread(()->{
            reentrantLockDemoPra.print("c",condition5,condition3);
        }).start();
        Thread.sleep(1*1000);
        reentrantLockDemoPra.lock();
        try {
            condition3.signal();
        }finally {
            reentrantLockDemoPra.unlock();
        }
    }
}

class MyReentrantLock extends ReentrantLock {
    /**
     * 循环次数
     */
    private int loopNum;

    public MyReentrantLock(int loopNum) {
        this.loopNum = loopNum;
    }

    public void print(String content, Condition condition1, Condition condition2) {
        for (int i = 0; i < loopNum; i++) {
            // 锁住
            lock();
            try {
                // 等待
                condition1.await();
                // 输出
                System.out.print(content);
                // 唤醒
                condition2.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                unlock();
            }
        }
    }

}

class ReentrantLockDemoPra extends ReentrantLock {
    /**
     * 定义循环次数
     */
    private int loopNum;

    public ReentrantLockDemoPra(int loopNum) {
        this.loopNum = loopNum;
    }

    /**
     * 打印
     *
     * @param content
     * @param own
     * @param next
     */
    public void print(String content, Condition own, Condition next) {
        for (int i = 0; i < loopNum; i++) {
            // try
            lock();
            try {
                own.await();
                System.out.print(content);
                next.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                unlock();
            }
        }
    }
}
